package org.mspring.mlog.service;

import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.util.Date;

import javax.imageio.ImageIO;

import org.apache.commons.codec.digest.DigestUtils;
import org.mspring.mlog.dao.PhotoDao;
import org.mspring.mlog.entity.Album;
import org.mspring.mlog.entity.Photo;
import org.mspring.platform.config.ConfigService;
import org.mspring.platform.dao.Page;
import org.mspring.platform.dao.query.QueryBuilder;
import org.mspring.platform.qiniu.QiniuStorageService;
import org.mspring.platform.security.SecurityUtils;
import org.mspring.platform.security.entity.User;
import org.mspring.platform.security.exception.UNLoginException;
import org.mspring.platform.utils.ImageUtils;
import org.mspring.platform.utils.MimeTypeUtils;
import org.mspring.platform.utils.Size;
import org.mspring.platform.utils.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.qiniu.api.io.PutRet;

/**
 *
 * @author Gao Youbo
 * @since 2012-10-17
 */
@Service
@Transactional
public class PhotoService {

    public static final String PHOTO_KEY_PRE = "photo-";
    public static final int DEFAULT_MAX_WIDTH = 1440;
    public static final int DEFAULT_MAX_HEIGHT = 900;

    @Autowired
    private PhotoDao photoDao;

    @Autowired
    private QiniuStorageService storageService;

    @Autowired
    private ConfigService configService;

    @Autowired
    private QiniuStorageService qiniuStorageService;

    public Photo get(long id) {
        return photoDao.get(id);
    }

    public Page<Photo> listPage(QueryBuilder queryBuilder, Page<Photo> page) {
        return photoDao.listPage(queryBuilder, page);
    }

    public Long insert(byte[] bytes, long album) throws Exception {
        User currentUser = SecurityUtils.getCurrentUser();
        if (currentUser == null) {
            throw new UNLoginException();
        }
        BufferedImage image = ImageIO.read(new ByteArrayInputStream(bytes));
        if (isLimitSize(image.getWidth(), image.getHeight())) {
            Size maxSize = getMaxSize();
            Size size = getZoomSize(image.getWidth(), image.getHeight(), (int) maxSize.getWidth(), (int) maxSize.getHeight());
            image = ImageUtils.resize(image, (int) size.getWidth(), (int) size.getHeight());
        }
        String mimeType = MimeTypeUtils.getMimeType(bytes);
        String formatName = MimeTypeUtils.getExtension(mimeType);
        int width = image.getWidth();
        int height = image.getHeight();
        byte[] imageBytes = ImageUtils.getByteArray(image, formatName);
        int size = imageBytes.length;

        // 处理图片
        String key = PHOTO_KEY_PRE + DigestUtils.md5Hex(bytes);
        PutRet ret = storageService.put(key, imageBytes);
        if (!ret.ok()) {
            throw new Exception("上传图片失败");
        }
        String url = storageService.getUrl(ret);

        Photo photo = new Photo();
        photo.setAlbum(new Album(album));
        photo.setName("");
        photo.setUrl(url);
        photo.setWidth(width);
        photo.setHeight(height);
        photo.setSize(size);
        photo.setCreateUser(currentUser);
        photo.setCreateTime(new Date());
        photo.setUpdateTime(new Date());
        return photoDao.insert(photo);
    }

    public void delete(Long... ids) {
        if (ids == null || ids.length == 0) {
            return;
        }
        for (Long id : ids) {
            Photo photo = get(id);
            if (photo == null) {
                continue;
            }
            photoDao.delete(photo);
            qiniuStorageService.deleteByUrl(photo.getUrl());
        }
    }

    public void update(Photo photo) {
        photo.setUpdateTime(new Date());
        photoDao.update(photo);
    }

    /**
     * 是否限定图片大小
     *
     * @param sourceWidth
     *            原图片宽度
     * @param sourceHeight
     *            原图片高度
     * @return
     */
    private boolean isLimitSize(int sourceWidth, int sourceHeight) {
        boolean isLimit = "true".equals(configService.getConfig("photo_islimit_size"));
        if (!isLimit) {
            return false;
        }
        Size size = getMaxSize();
        // 原始图片的大小是否超出限定范围
        if (sourceWidth < size.getWidth() && sourceHeight < size.getHeight()) {
            return false;
        }
        return true;
    }

    /**
     * 获取最大size
     *
     * @return
     */
    private Size getMaxSize() {
        String string_ori_width = configService.getConfig("photo_max_width");
        String string_ori_height = configService.getConfig("photo_max_height");
        int MAX_WIDTH = StringUtils.isBlank(string_ori_width) ? DEFAULT_MAX_WIDTH : Integer.parseInt(string_ori_width);
        int MAX_HEIGHT = StringUtils.isBlank(string_ori_height) ? DEFAULT_MAX_HEIGHT : Integer.parseInt(string_ori_height);
        return new Size(MAX_WIDTH, MAX_HEIGHT);
    }

    /**
     * 按照特定比例缩放
     *
     * @param sourceW
     *            原图宽度
     * @param sourceH
     *            原图高度
     * @param targetW
     *            目标高度
     * @param targetH
     *            目标宽度
     */
    private Size getZoomSize(Integer sourceW, Integer sourceH, Integer targetW, Integer targetH) {
        double sx = (double) targetW / sourceW;
        double sy = (double) targetH / sourceH;
        if (sx > sy) {
            sx = sy;
            targetW = (int) (sx * sourceW);
        } else {
            sy = sx;
            targetH = (int) (sy * sourceH);
        }
        return new Size(targetW, targetH);
    }
}
